package modelewithstatemachine;

import java.util.ArrayList;

import modele.Manager;

import statemachines.State;
import statemachines.StateMachine;


// Faites pas gaffe à cette classe.

public class TaxiWithStateMachine {
	private double x;
	private double y;
	private double xDest;
	private double yDest;
	private double vitesse;
	
	private StateMachine machine;
	private ClientAroundStateMachineOMGIMSURROUNDED aChercher;
	private ArrayList<ClientAroundStateMachineOMGIMSURROUNDED> aConduire;
	private boolean clientAtteint;
	
	public TaxiWithStateMachine(int vitesse) {
		this.vitesse = vitesse;
		
		double rTaxi = Math.random() * (double)ManagerWithTaxiWithStateMachinePleaseIWantALongerName.getCityRadius();
		double thetaTaxi = 2D * Math.PI * Math.random();
//		System.out.println("New taxi : r="+rTaxi+", theta="+thetaTaxi);
		
		x = xDest = rTaxi * Math.cos(thetaTaxi);
		y = yDest = rTaxi * Math.sin(thetaTaxi);
		
		aChercher = null;
		aConduire = new ArrayList<ClientAroundStateMachineOMGIMSURROUNDED>(2);
		clientAtteint = false;
		
		machine = new StateMachine();
		
		machine.addState(new State("enAttente", machine) {
			public void doAction() { /* Rien du tout */ }
			
			public void checkNextStep() {
				if(aChercher != null) {
					aChercher.estPrisEnCharge();
					goTo("chercherClient");
				}
			}
		});
		
		
		machine.addState(new State("chercherClient", machine) {
			public void doAction() {
				//Distance restante a parcourir
				clientAtteint = avancer();
			}
			
			public void checkNextStep() {
				System.out.println(aChercher);
				if(clientAtteint) {
					aChercher.estDansTaxi();
					
					aConduire.add(aChercher);
					aChercher = null;
					
					xDest = aConduire.get(0).getXDest();
					yDest = aConduire.get(0).getYDest();
					
					goTo("conduireClient");
				}
			}
		});
		
		
		machine.addState(new State("conduireClient", machine) {
			public void doAction() {
				clientAtteint = avancer();
			}
			
			public void checkNextStep() {
				if(aChercher != null) {
					aChercher.estPrisEnCharge();
					goTo("chercherClient");
				}
				else if(clientAtteint) {
					// Déposer le client puis ...
					aConduire.get(0).estArrive();
					aConduire.remove(0);
					
					clientAtteint = false;
					if(aConduire.isEmpty())
						goTo("enAttente");
					else {
						xDest = aConduire.get(0).getXDest();
						yDest = aConduire.get(0).getYDest();
					}
				}
			}
		});
		
		machine.setStartState("enAttente");
	}
	
	public double getX() {
		return x;
	}
	
	public double getY() {
		return y;
	}
	
	public double getXDest() {
		return xDest;
	}
	
	public double getYDest() {
		return yDest;
	}
	
	public boolean chercherClient(ClientAroundStateMachineOMGIMSURROUNDED client) {
		if(aChercher != null)
			return false;
		else if(aConduire.isEmpty()) {
			admettreClient(client);
			return true;
		}
		else if(aConduire.size() == 1) {
			double dist = Math.sqrt((yDest - y)*(yDest - y) + (xDest - x)*(xDest - x));
			
			double newClientDist = Math.sqrt((client.getY() - y)*(client.getY() - y) + (client.getX() - x)*(client.getX() - x));
			
			if(newClientDist / dist < 0.2D) {
				admettreClient(client);
				return true;
			}
			else {
				return false;
			}
		}
		else
			return false;
	}
	
	private void admettreClient(ClientAroundStateMachineOMGIMSURROUNDED client) {
		aChercher = client;
		System.out.println("Je prends en charge " + client);
		
		xDest = client.getX();
		yDest = client.getY();
	}
	
	private boolean avancer() {
		double dist = Math.sqrt((yDest - y)*(yDest - y) + (xDest - x)*(xDest - x));
		
		if(dist < vitesse) {
			x = xDest;
			y = yDest;
			
			return true;
		}
		else {
			x += (vitesse/dist)*(xDest - x);
			y += (vitesse/dist)*(yDest - y);
			
			return false;
		}
		
	}
	
	public void update() {
		machine.playNextStep();
	}
	
	public boolean hasClients() {
		return !aConduire.isEmpty();
	}
	
	public int getClientsCount() {
		return aConduire.size();
	}
}
